package org.su.webadapter.interceptor;

import org.su.generalmvc.IModel;
import org.su.generalmvc.annotaion.Param;
import org.su.generalmvc.core.ActionInvocation;
import org.su.generalmvc.core.InitialContext;
import org.su.generalmvc.core.Interceptor;
import org.su.generalmvc.entity.PojoCache;
import org.su.webadapter.validate.*;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 验证拦截器，效率极低，后面可以考虑定义对于的ValidatorEditor 将验证放在editor 里面去实现。
 * Created by 杨川 on 2015-12-09 17:15:36.
 */
public class ValidatorInterceptor implements Interceptor {
    HashMap<String,IValidator> validatorContext = null;

    @Override
    public void destroy() {
    }

    @Override
    public void init() {
        validatorContext = new HashMap<>();
        validatorContext.put(NotNull.class.getName(), new NotNullValidator());
        validatorContext.put(Null.class.getName(), new NullValidator());
        validatorContext.put(Size.class.getName(), new SizeValidator());
        validatorContext.put(Max.class.getName(), new MaxValidator());
        validatorContext.put(Min.class.getName(), new MinValidator());
        validatorContext.put(Pattern.class.getName(), new PatternValidator());
    }

    @Override
    public Object intercept(ActionInvocation invocation) throws Exception {
        Object[] args = invocation.getArgs();
        if(args == null || args.length == 0){
             return invocation.invoke();
        }
        Method method = invocation.getProxy().getAction();
        String[] params = invocation.getProxy().getActionConfig().getParamNames();
        Map<String, Class<?>> beanTypes = invocation.getProxy()
                .getActionConfig().getBeanParams();

        IModel model = invocation.getModel();

        String name = null;

         Annotation[][] annotations = method.getParameterAnnotations();
         int i =0;
         boolean flag =true;
        String msg = null;
        PojoCache pc = null;
        String prifix = null;
        List<String> names = null;
        IValidator validator = null;
        for(Annotation[] items : annotations){

             for(Annotation item : items){
                 validator = validatorContext.get(item.annotationType().getName());
                 if(item instanceof Valid){
                     pc = InitialContext.getInstance().getContext().getPojoContext().get(beanTypes.get(params[i]).getName());
                     if(pc == null){
                         return null;
                     }
                     prifix = params[i] + ".";
                     names = pc.getMethodNames();
                     for(int j=0;j<names.size();j++){
                         name = prifix + names.get(j);
                         Annotation[] proMethods = pc.getMethods().get(j).getAnnotations();
                         for(Annotation pItem : proMethods) {
                             validator = validatorContext.get(pItem.annotationType().getName());
                             if (validator != null && (msg = validator.validate(pc.getReadMethods().get(j).invoke(args[i]), pItem)) != null) {
                                 model.addFieldErrors(name, msg);
                             }
                         }

                     }
                     break;
                 }else if(validator != null && (msg = validator.validate(args[i],item)) != null){
                    model.addFieldErrors(params[i], msg);
                 }
             }
             i++;
         }
        msg = null;
        pc = null;
        prifix = null;
        names = null;
        validator = null;
        method = null;
        params = null;
        args = null;
        ValidateErrors validateErrors = (ValidateErrors)invocation.getRequest().getAttribute(ValidateErrors.VALIDATE_ERRORS);
        if(validateErrors != null){
            validateErrors.setErrors(model.getFieldErrors());
            return invocation.invoke();
        }
        if(model.getFieldErrors() != null && model.getFieldErrors().size()>0){
            return null;
        }else{
            return invocation.invoke();
        }

    }



}
